"""
    查询系统服务器
    View  接收客户端请求，调用（控制器）方法，获取返回值　返回给客户端
    Collector 　根据View调用Model返回数据给View
    Model　　　　提供数据
    应用技术　：　soket套接字　Process进程　Mysql数据库
    1.编写模板层　连接数据库
    2.编写视图函数
    3.编写控制器方法
"""
from socket import *
import pymysql
from multiprocessing import Process
import time
import sys

args = {
    'host': 'localhost',
    'port': 3306,
    'user': 'root',
    'password': '123456',
    'database': 'dict',
    'charset': 'utf8',
}


class DictView():
    def __init__(self):
        self.sock = self._connect()

    def _connect(self):
        """创建套接字"""
        sock = socket()
        sock.bind(('0.0.0.0', 1942))
        return sock

    def _access(self):
        """ 分配连接"""
        while True:
            self.sock.listen(5)
            connfd, addr = self.sock.accept()
            print(f'Connect to {addr}')
            self.my_process = Myprocess(connfd)
            self.my_process.start()

    def start(self):
        self._access()
        print('已分配进程')


class Myprocess(Process):
    def __init__(self, connfd):
        super().__init__()
        self.connfd = connfd
        self.collector = DictCollector(self.connfd)

    def run(self):
        """重定义run方法"""
        print('进程创建了')
        self.collector.handler()


class DictCollector(object):
    """处理器，负责处理客户端需求，返回数据给客户端"""

    def __init__(self, connfd):
        self.connfd = connfd
        self.dict_model = DictModel()

    def handler(self):
        while True:
            data = self.connfd.recv(1024).decode()
            if not data:
                print('客户端异常退出')
                self.connfd.close()
                break
            data_head = data.split(' ', 1)[0]  # 获取请求头
            data_body = data.split(' ', 1)[1]
            if data_head == 'IN':  # 登录
                """调用登录功能"""
                username, password = data_body.split('-', 1)
                self.login_decide(username, password)

            elif data_head == 'CREAT':  # 注册
                username, password = data_body.split('-', 1)
                self.login(username, password)

            elif data_head == 'GET':  # 查询
                print('查询中')
                self.query(data_body)
            elif data_head == 'OUT':  # 注销
                print('客户端注销.....')
                break

    def login_decide(self, username, password):
        """向数据库确定账号密码是否正确,返回账号密码或False"""
        self.connfd.send(b'200')
        if self.dict_model.login_decide(username, password):
            self.connfd.send(b'200')
            print('用户登录')
        else:
            self.connfd.send(b'404')

    def login(self, username, password):
        self.connfd.send(b'200')
        if self.dict_model.login(username, password):
            self.connfd.send(b'200')
            print('用户注册')
        else:
            self.connfd.send(b'404')
            print('账号已存在')

    def query(self, message):
        print(f'用户查询单词{message}')
        word = message.split(' ')[0]
        username = message.split(' ')[1]
        if word != 'SELECT':
            mean = self.dict_model.get_mean(word, username)
            print('准备发送查询结果给客户端')
            if mean:
                self.connfd.send(b'200')
                time.sleep(0.2)
                self.connfd.send(mean[0].encode())
            else:
                self.connfd.send(b'404')
        else:
            select = self.dict_model.get_query_log(username)
            print(f'查询结果{select}')
            if select:
                self.connfd.send(b'200')
                time.sleep(0.2)
                print('已向客户端发送结果')
                for i in select:
                    i = str(i)
                    self.connfd.send(i.encode())
                    time.sleep(0.2)
                self.connfd.send(b'##')
            else:
                self.connfd.send(b'404')


class DictModel():
    """
        连接数据库，提供数据
    """

    def __init__(self, word=''):
        """
            connect 建立连接
            cur 建立游标
            username 用来查询的用户名
            word 查询单词
        """
        self._connect = pymysql.connect(**args)
        self._cur = self._connect.cursor()
        self._word = word

    def login_decide(self, username, password):
        """判定登录"""
        data = [username, password]
        message = 'select username,password from user where username=%s and password=%s'
        self._cur.execute(message, data)
        return self._cur.fetchone()

    def login(self, username, password):
        """添加用户"""
        data = [username, password]
        message = 'insert into user(username,password) values (%s,%s)'
        try:
            self._cur.execute(message, data)
            self._connect.commit()
            return self.login_decide(username, password)
        except:
            return None

    def get_mean(self, word, username):
        """查询注释"""
        data = [word]
        message = 'select mean from dict_words where word=%s'
        self._cur.execute(message, data)
        number = self._cur.fetchone()
        if number:
            data = [username, word]
            message = 'insert into query_log (uname, word) values (%s,%s)'
            self._cur.execute(message, data)
            self._connect.commit()
            return number
        else:
            return None

    def get_query_log(self, username):
        """查询查询记录"""
        data = [username]
        message = 'select uname,word,createtime from query_log where uname=%s order by createtime desc'
        self._cur.execute(message, data)
        return self._cur.fetchmany(10)


if __name__ == '__main__':
    view = DictView()
    view.start()
